package sma.agents;
import java.util.Vector;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class bookBuyerAgent extends Agent {
	private String targetBookTitle;
//	private AID[] sellerAgents = {new AID("seller1", AID.ISLOCALNAME),
//										new AID("seller2", AID.ISLOCALNAME)};
	private AID[] sellerAgents;
	private bookBuyerGui myGUI;
	protected void setup(){
		
		System.out.println("Buyer agent " + this.getAID().getName() + "is ready !");
		
		//List of seller agent as argument
		Object[] args = this.getArguments();
		if (args != null && args.length > 0){
			this.targetBookTitle = (String) args[0];
			System.out.println("Target book is : " + this.targetBookTitle);
			
			//Inserer un TicketBehaviour qui demande a vendeur agent chaque minute = 60000
			this.addBehaviour(new TickerBehaviour(this,30000){
				protected void onTick(){
					
					System.out.println("Trying to buy " + targetBookTitle);
					DFAgentDescription template = new DFAgentDescription();
					ServiceDescription sd = new ServiceDescription();
					sd.setType("book-selling");
					sd.setName("JADE-book-trading");
					template.addServices(sd);
					try{
						DFAgentDescription[] result = DFService.search(this.myAgent, template);
						System.out.println("Found the fllowing seller agents");
						sellerAgents = new AID[result.length];
						for(int i = 0; i < result.length; i++){
							sellerAgents[i] = result[i].getName();
							System.out.println(sellerAgents[i].getName());
						}
					}
					catch(FIPAException e){
						e.printStackTrace();
					}
					
					myAgent.addBehaviour(new RequestPerformer());
				}
			});
		}
		else{
			System.out.println("No book title specified");
			doDelete();
		}
	}
	
	public interface bookBuyerGui{
		void setAgent (bookBuyerAgent a);
		void show();
		void hide();
		void dispose();
		void notifyUser(String message);
	}
	
	protected void takeDown(){
		if (myGUI != null){
			myGUI.dispose();
		}
		System.out.println("Buyer-agent " + this.getAID().getName() + "terminated !");
	}
	
	public void purchase(){
		return;
	}
	
	public class OverbearingBehaviour extends Behaviour{
		public void action(){
			while(true){
				//
			}
		}
		
		public boolean done(){
			return true;
		}
	}
	
	public class myOneShotBehaviour extends OneShotBehaviour{
		public void action(){
			
		}
	}
	
	public class myCyclicBehaviour extends CyclicBehaviour{
		public void action(){
			
		}
	}
	
	public class myMultiTaskBehaviour extends Behaviour{
		private int step = 0;
		public void action(){
			switch (step){
			case 0:
				step++;
				break;
			case 1:
				step++;
				break;
			case 2:
				step++;
				break;
			default :
				break;
			}
		}
		
		public boolean done(){
			return step==3;
		}
	}

	//SequentialBehaviour

	//ParallelBehaviour
	
	//FSMBehaviour
	
	private class RequestPerformer extends Behaviour{
		private AID bestSeller;
		private int bestPrice;
		private int repliesCnt;
		private jade.lang.acl.MessageTemplate mt;
		private int step = 0;
		public void action(){
			System.out.println("RequestPerformer step : " + step);
			switch(step){
			case 0:
				jade.lang.acl.ACLMessage msg = new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.CFP);
				for(int i = 0; i < sellerAgents.length; i++){
					msg.addReceiver(sellerAgents[i]);
				}
				msg.setContent(targetBookTitle);
				msg.setConversationId("book-trade");
				msg.setReplyWith("cfp " + System.currentTimeMillis());
				this.myAgent.send(msg);
				
				mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book-trade"),
						MessageTemplate.MatchInReplyTo(msg.getReplyWith()));
				step = 1;
				break;
			case 1:
				jade.lang.acl.ACLMessage reply = this.myAgent.receive(mt);
				if (reply != null){
					if (reply.getPerformative() == ACLMessage.PROPOSE){
						int price = Integer.parseInt(reply.getContent());
						if (bestSeller == null || price < this.bestPrice){
							bestPrice = price;
							bestSeller = reply.getSender();
						}
					}
					repliesCnt++;
					if (repliesCnt >= sellerAgents.length){
						step = 2;
						System.out.println(bestSeller);
					}
				}
				else{
					this.block();
				}
				break;
			case 2:
				ACLMessage order = new ACLMessage(ACLMessage.PROPOSE);
				order.addReceiver(bestSeller);
				order.setContent(targetBookTitle);
				order.setConversationId("book-trade");
				order.setReplyWith("order " + System.currentTimeMillis());
				this.myAgent.send(order);
				mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book-trade"),
						MessageTemplate.MatchInReplyTo(order.getReplyWith()));
				step = 3;
				break;
			case 3 :
				reply = this.myAgent.receive(mt);
				if (reply != null){
					System.out.println("3.reply" + reply);
					if(reply.getPerformative() == ACLMessage.INFORM){
						System.out.println(targetBookTitle + " successfully purchased from agent " + reply.getSender().getName());
						System.out.println("Price = " + this.bestPrice);
						doDelete();
					}
					else{
						System.out.println("Attempt failed: requested book already sold.");
					}
					step = 4;
				}
				else
					this.block();
				break;
			}
		}
		
		public boolean done(){
			if (step == 2 && bestSeller == null) {
				System.out.println("Attempt failed: "+targetBookTitle+" not available for sale");
			}
			return ((step == 2 && bestSeller == null) || step == 4);
		}
	}
}